﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Math;

using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion

namespace Weazel.Math.Test
{
  [TestClass]
  public class TestAddition
  {
    /**************************************************************************
		 * Addition (Signed)
		 **************************************************************************/
    [TestMethod]
    public void TestAddition_1()
    {
      Integer a = new Integer(32, 100, false);
      Integer b = new Integer(32, 125, false);
      Integer r = a + b;

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("225", r.ToDecimalString());

      r = new Integer(32, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("225", r.ToDecimalString());
    }

    [TestMethod]
    public void TestAddition_2()
    {
      Integer a = new Integer(32, 100, true);
      Integer b = new Integer(32, 125, false);
      Integer r = a + b;

      Assert.IsTrue(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("225", r.ToDecimalString());

      r = new Integer(32, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("225", r.ToDecimalString());
    }

    /**************************************************************************
		 * Addition (Signed)
		 **************************************************************************/
    [TestMethod]
    public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_1()
    {
      Integer a = new Integer(64, "0xFFFFFFFFFFFFFFFF", false);
      Integer b = new Integer(32, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(64, r.Width);
      Assert.AreEqual("1", r.ToHexadecimalString()); // result has been truncated

      // user defined result ..
      r = new Integer(96, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("10000000000000001", r.ToHexadecimalString());
    }

    [TestMethod]
    public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_2()
    {
      Integer a = new Integer(96, "0xFFFFFFFFFFFFFFFF", false);
      Integer b = new Integer(64, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("10000000000000001", r.ToHexadecimalString()); 

      // user defined result ..
      r = new Integer(32, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
    }

    [TestMethod]
    public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_3()
    {
      Integer a = new Integer(96, "0xFFFFFFFFFFFFFFFF", false);
      Integer b = new Integer(32, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("10000000000000001", r.ToHexadecimalString());

      // user defined result ..
      r = new Integer(64, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(64, r.Width);
      Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
    }

    [TestMethod]
    public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_1()
    {
      Integer a = new Integer(32, "0xFFFFFFFF", false);
      Integer b = new Integer(64, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(64, r.Width);
      Assert.AreEqual("100000001", r.ToHexadecimalString()); // result truncated

      // user defined result ..
      r = new Integer(96, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("100000001", r.ToHexadecimalString());
    }

    [TestMethod]
    public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_2()
    {
      Integer a = new Integer(32, "0xFFFFFFFF", false);
      Integer b = new Integer(96, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("100000001", r.ToHexadecimalString()); 

      // user defined result ..
      r = new Integer(64, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(64, r.Width);
      Assert.AreEqual("100000001", r.ToHexadecimalString());
    }

    [TestMethod]
    public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_3()
    {
      Integer a = new Integer(64, "0xFFFFFFFFFFFFFFFF", false);
      Integer b = new Integer(96, 2, false);
      Integer r = a + b;

      // using the overloaded operator ..
      Assert.IsFalse(r.Signed);
      Assert.AreEqual(96, r.Width);
      Assert.AreEqual("10000000000000001", r.ToHexadecimalString()); 

      // user defined result ..
      r = new Integer(32, false);
      Integer.Add(ref r, a, b);

      Assert.IsFalse(r.Signed);
      Assert.AreEqual(32, r.Width);
      Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
    }

    [TestMethod]
    public void TestAddition_SingleBit()
    {
      Integer a = new Integer(1, false);
      Integer b = new Integer(1, false);

      a.Assign(0);
      b.Assign(0);

      Integer r = a + b;

      Assert.AreEqual("0", r.ToDecimalString());
      Assert.AreEqual(1, r.Width);

      a.Assign(0);
      b.Assign(1);

      r = a + b;

      Assert.AreEqual("1", r.ToDecimalString());
      Assert.AreEqual(1, r.Width);

      a.Assign(1);
      b.Assign(1);

      r = a + b;

      Assert.AreEqual("0", r.ToDecimalString());
      Assert.AreEqual(1, r.Width);
    }
  }
}
